package com.hashmap.test01;

import java.util.Objects;

/**
 * @author XiaoPan
 * date: 2022/1/17 16:13
 * <p>
 * action:  实现 hashmap
 */
public class TestMap1<K, V> {


    // hashmap 初始 容量 为 16
    private Integer capacity = 16;

    private Node<K, V>[] objects;

    private Integer size = 0;


    //初始化
    public TestMap1() {
        this.objects = new Node[capacity];
    }

    public int size() {
        return size;
    }

    // 增加
    public void put(K key, V value) {
        if (size >= objects.length / 4 * 3) {
            capacityExpansion3();
        }

        if (key == null) return;

        int i = key.hashCode();
        Node<K, V> newNode = new Node<>(key, value, null);

        int i1 = i % capacity;

        if (objects[i1] == null) {
            size++;
            objects[i1] = newNode;
            return;
        }

        Node<K, V> node = forEac2(objects[i1], key);

        if (node == null) {
//            node.setNext(newNode);
//            没有找到
            if (objects[i1].getNext() != null) {
                //有第一个节点
                //将 新的节点 放到 第一个
                newNode.setNext(objects[i1].getNext());
            }
            objects[i1].setNext(newNode);
//            大小加1
            size++;
        } else {
            node.setValue(value);
        }
    }

    public V get(K key) {
        int i = key.hashCode();
        int i1 = i % capacity;
        if (objects[i1] == null) return null;
        Node<K, V> node = forEac2(objects[i1], key);
        if (node == null) {
            return null;
        }
        return node.getValue();
    }

    /**
     * 如果有的话 就 返回 那个 节点  没有的话 就返回null;
     */
    private Node<K, V> forEac2(Node<K, V> node, K key) {
        while (node != null && !node.equals(key)) {
            //没有找到
            node = node.getNext();
        }

        return node;
    }

    // 不需要第一层循环
    public boolean containsKey(K key) {
        int i = key.hashCode() % capacity;

        Node<K, V> tempNode = objects[i];

        if (tempNode == null) {
            return false;
        }

        do {
            if (tempNode.equals(key)) {
                return true;
            }
            tempNode = tempNode.getNext();
        } while (tempNode.getNext() != null);

        return false;
    }

    public void capacityExpansion3() {
        capacity = capacity * 2;
        Node<K, V>[] tempStr = objects;
        Node<K, V>[] newStr = new Node[capacity];

        for (Node<K, V> kvNode : tempStr) {
            //如果没有 就 跳过
            while (kvNode != null) {
                K key = kvNode.getKey();

                int index = key.hashCode() % capacity;
                Node<K, V> node = new Node<>(kvNode.getKey(), kvNode.getValue(), newStr[index]);
                newStr[index] = node;

                kvNode = kvNode.getNext();
            }
        }

        objects = newStr;
    }

    public V remove(K key) {

        int i = key.hashCode() % capacity;

        if (objects[i] == null) return null;

        Node<K, V> tempStr = objects[i];

        //第一个就相等
        if (tempStr.equals(key)) {
            V value = objects[i].getValue();
            objects[i] = tempStr.getNext();
            size--;
            return value;
        }

        while (tempStr.getNext() != null) {
            if (tempStr.getNext().equals(key)) {
                //找到了
                V value = tempStr.getNext().getValue();
                tempStr.setNext(tempStr.getNext().getNext());
                size--;
                return value;
            }

            tempStr = tempStr.getNext();
        }
        //没有找到
        return null;
    }

    private static class Node<T, E> {
        T key;
        E value;
        Node<T, E> next;

        public Node(T key, E value, Node<T, E> next) {
            this.key = key;
            this.value = value;
            this.next = next;
        }

        public T getKey() {
            return key;
        }

        public E getValue() {
            return value;
        }

        public void setValue(E value) {
            this.value = value;
        }

        public Node<T, E> getNext() {
            return next;
        }

        public void setNext(Node<T, E> next) {
            this.next = next;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null) return false;

            if (getClass() != o.getClass()) {
                return key.equals(o);
            } else {
                return Objects.equals(key, ((Node<?, ?>) o).key);
            }
        }
    }
}

